package git.soulbgm.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import git.soulbgm.common.constant.Constant;
import git.soulbgm.common.enums.Status;
import git.soulbgm.common.pojo.PageInfo;
import git.soulbgm.mapper.MenuMapper;
import git.soulbgm.mapper.RoleMenuMapper;
import git.soulbgm.pojo.dto.MenuDto;
import git.soulbgm.pojo.entity.Menu;
import git.soulbgm.pojo.entity.RoleMenu;
import git.soulbgm.pojo.vo.MenuTreeVo;
import git.soulbgm.security.service.PermissionService;
import git.soulbgm.service.MenuService;
import git.soulbgm.utils.ModelBuilder;
import git.soulbgm.utils.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 菜单相关业务逻辑
 *
 * @author SoulBGM
 * @date 2020-09-10 17:30:42
 */
@Service
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private PermissionService permissionService;

    private Example getMenuExample(MenuDto menu) {
        Example menuExample = new Example(Menu.class);
        Example.Criteria criteria = menuExample.and();
        criteria.andEqualTo("delFlag", Status.EXIST.code);
        if (StringUtil.isNotEmpty(menu.getMenuName())) {
            criteria.andLike("menuName", "%" + menu.getMenuName() + "%");
        }
        if (menu.getMenuType() != null) {
            criteria.andEqualTo("menuType", menu.getMenuType());
        }
        if (menu.getVisible() != null) {
            criteria.andEqualTo("visible", menu.getVisible());
        }
        if (menu.getStatus() != null) {
            criteria.andEqualTo("status", menu.getStatus());
        }
        if (menu.getCreateStartTime() != null && menu.getCreateEndTime() != null) {
            criteria.andBetween("createTime", menu.getCreateStartTime(), menu.getCreateEndTime());
        }
        return menuExample;
    }

    @Override
    public PageInfo find(Integer pageNum, Integer pageSize, MenuDto menu) {
        PageHelper.startPage(pageNum, pageSize);
        Example menuExample = getMenuExample(menu);
        List<Menu> list = menuMapper.selectByExample(menuExample);
        return PageInfo.getPageInfo((Page) list);
    }

    @Override
    public Menu findById(Long id) {
        Menu menu = menuMapper.selectByPrimaryKey(id);
        return menu;
    }

    @Override
    public List<MenuTreeVo> findByRoleId(Long roleId) {
        List<Long> menuIdList = getMenuIdList(roleId);
        if (menuIdList.isEmpty()) {
            return Arrays.asList();
        }
        Example menuExample = new Example(Menu.class);
        menuExample.and().andIn("id", menuIdList);
        List<Menu> menuList = menuMapper.selectByExample(menuExample);
        List<MenuTreeVo> treeVoList = getMenuTreeVo(0L, menuList);
        return treeVoList;
    }

    @Override
    public List<Long> getMenuIdList(Long roleId) {
        RoleMenu roleMenuQueryParam = new RoleMenu();
        roleMenuQueryParam.setRoleId(roleId);
        List<RoleMenu> roleMenuList = roleMenuMapper.select(roleMenuQueryParam);
        List<Long> menuIdList = new ArrayList<>();
        for (RoleMenu roleMenu : roleMenuList) {
            menuIdList.add(roleMenu.getMenuId());
        }
        return menuIdList;
    }

    @Override
    public List<MenuTreeVo> findByUserId(Long userId) {
        List<Menu> menuList = permissionService.getUserMenu(userId);
        if (menuList.isEmpty()) {
            return Arrays.asList();
        }
        return getMenuTreeVo(0L, menuList);
    }

    @Override
    public List<MenuTreeVo> findTree() {
        Example menuExample = new Example(Menu.class);
        menuExample.and()
                .andEqualTo("delFlag", Status.EXIST.code)
                .andEqualTo("status", Status.NORMAL.code)
                .andEqualTo("visible", Status.NORMAL.code);
        List<Menu> menuList = menuMapper.selectByExample(menuExample);
        List<MenuTreeVo> treeVoList = getMenuTreeVo(0L, menuList);
        return treeVoList;
    }

    private List<MenuTreeVo> getMenuTreeVo(Long parentId, List<Menu> menuList) {
        List<MenuTreeVo> treeVoList = new ArrayList<>();
        for (Menu menu : menuList) {
            if (menu.getParentId().equals(parentId)) {
                MenuTreeVo vo = new MenuTreeVo();
                BeanUtils.copyProperties(menu, vo);
                if (vo.getMenuType() == Constant.MENU_TYPE_DIRECTORY || vo.getMenuType() == Constant.MENU_TYPE_MENU) {
                    vo.setChild(getMenuTreeVo(menu.getId(), menuList));
                }
                treeVoList.add(vo);
            }
        }
        return treeVoList;
    }

    @Override
    public Boolean addRoleMenu(Long roleId, List<Long> menuIdList) {
        List<RoleMenu> roleMenuList = new ArrayList<>(menuIdList.size());
        for (Long menuId : menuIdList) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(menuId);
            ModelBuilder.builder(roleMenu);
            roleMenuList.add(roleMenu);
        }
        return roleMenuMapper.insertList(roleMenuList) == roleMenuList.size();
    }

    @Override
    public Menu add(Menu menu) {
        ModelBuilder.builder(menu);
        int result = menuMapper.insertSelective(menu);
        if (result > 0) {
            return menu;
        } else {
            return null;
        }
    }

    @Override
    public Boolean update(Menu menu) {
        int result = menuMapper.updateByPrimaryKeySelective(menu);
        return result > 0;
    }

    @Override
    public void deleteRoleMenu(Long roleId) {
        Example example = new Example(RoleMenu.class);
        example.and().andEqualTo("roleId", roleId);
        int result = roleMenuMapper.deleteByExample(example);
    }

    @Override
    public Boolean delete(List idList) {
        Example menuExample = new Example(Menu.class);
        menuExample.and().andIn("id", idList);
        int result = menuMapper.deleteByExample(menuExample);
        return result > 0;
    }
}
